package com.sammy.appmonitor.communication;

import java.util.List;

import android.content.Context;
import com.sammy.utils.MyLog;

import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.sammy.appmonitor.config.MyConstants;
import com.sammy.appmonitor.contentprovider.RecordAppHistory;
import com.sammy.appmonitor.contentprovider.RecordMessagesOut;
import com.sammy.appmonitor.contentprovider.TableMessagesOut;
import com.sammy.appmonitor.main.MainActivity;
import com.sammy.appmonitor.storage.MySharedPreferences;
import com.sammy.utils.MyUtils;

public class ParseClient {
	//TODO:
	//make a singleton and throw errors?
	//make this clear all messages
	//run it when connectivity available or use an alarmmanager
	//query server and show on device results
	//use svn
	//TODO: if error do not continue
	
	public static final String TAG = "ParseClient.";
	public Context _context;
	private String appId;
	
	public static final String STATE_RUNNING = "running";
	public static final String STATE_FINISHED = "finished";
	
	
	public static final String SHARED_PREFERENCES_KEY = "ParseClientKey";
	
	private static ParseClient instance = null;
	
	private ParseClient(){		
	}
	
	public static ParseClient getInstance(){
		if(instance==null) instance = new ParseClient();
		return instance;
	}	
	
	public void consumeQueue(Context context){
		_context = context;
		Thread thread = new Thread(new Runnable(){
			public void run(){
				//avoid running this thread twice if a previous thread is already running
				//it can happen if multiple intents are triggered in a short period of time
				if(getState().equals(STATE_RUNNING)) return;
				try{
					startRunning();				
					RecordMessagesOut record = TableMessagesOut.getFirstRecord(_context);
					while(record!=null){
						sendMessagesToParseServer(record);
						TableMessagesOut.deleteRecord(_context,record.getId());
						record = TableMessagesOut.getFirstRecord(_context);					
					}								
					stopRunning();
					//MyUtils.dumpLogCatToSdCard();
				}catch(Exception e){
					MyLog.e(MainActivity.PROCESS_TAG,TAG+"consumeQueue exception: " + e.getMessage());
				}
			}
		});		
		thread.start();
	}
	
	private String getState(){
		return MySharedPreferences.getStringProperty(_context,SHARED_PREFERENCES_KEY,STATE_FINISHED);
	}
	
	private void startRunning(){
		MySharedPreferences.setStringProperty(_context, STATE_RUNNING, SHARED_PREFERENCES_KEY);		
	}
	
	private void stopRunning(){
		MySharedPreferences.setStringProperty(_context, STATE_FINISHED, SHARED_PREFERENCES_KEY);
	}
	
	private void sendMessagesToParseServer(RecordMessagesOut record)throws Exception{	
		
		String propertyDeviceId = MySharedPreferences.getStringProperty(_context, MySharedPreferences.KEY_DEVICES_OBJECT_ID, null); 
		if(propertyDeviceId == null){
			queryDeviceId();
			propertyDeviceId = MySharedPreferences.getStringProperty(_context, MySharedPreferences.KEY_DEVICES_OBJECT_ID, null);
		}
		
		appId = null;
		RecordAppHistory recordApp = new RecordAppHistory(record.getMessage());
		
		if(propertyDeviceId != null){					
			queryAppId(recordApp.getAppName());				
		}
		
		if(appId != null){					
			queryHistory(recordApp,record.getRecordTime());			
		}				
		
	}
	private void queryHistory(RecordAppHistory recordApp, String recordTime)throws Exception{
		try{
        	ParseObject object = new ParseObject(MyConstants.TN_HISTORY);		    	    
        	object.put(MyConstants.TF_HISTORY_APP_OBJECT_ID, appId);
        	String propertyDeviceId = MySharedPreferences.getStringProperty(_context, MySharedPreferences.KEY_DEVICES_OBJECT_ID, null);
        	object.put(MyConstants.TF_HISTORY_IMEI_OBJECT_ID, propertyDeviceId);
        	object.put(MyConstants.TF_HISTORY_ACTION, recordApp.getActionType());
        	object.put(MyConstants.TF_HISTORY_RECORD_TIME, recordTime);
        	object.save();
		}catch(Exception e){
			MyLog.e(MainActivity.PROCESS_TAG, TAG+"queryHistory - exception: " + e.getMessage() );
			throw new Exception("queryHistoryException - " + e.getMessage());
		}
	}
	
	private void queryAppId(String appName)throws Exception{
		try{
			ParseQuery query = new ParseQuery(MyConstants.TN_APPS);
			query.whereEqualTo(MyConstants.TF_APPS_APP_NAME, appName);
			List<ParseObject> list = query.find();
			if( list == null ){
		        MyLog.d(MainActivity.PROCESS_TAG, TAG+"queryAppId - app id for " + appName + " not found" );
			}
			else{		
	        	if( list.size() == 0 ){
	        		MyLog.d(MainActivity.PROCESS_TAG, TAG+"queryAppId.size == 0");
		        	//insert device id
		        	ParseObject object = new ParseObject(MyConstants.TN_APPS);		    	    
		        	object.put(MyConstants.TF_APPS_APP_NAME, appName);
		        	try{
		        		object.save();
		        	}catch(Exception e){
		        		MyLog.e(MainActivity.PROCESS_TAG, TAG+"queryAppId - save exception: " + e.getMessage() );
		        	}
		        	queryAppId(appName);	
	        	}
	        	else {
		        	ParseObject object = list.get(0);
		        	appId = object.getObjectId();
	        	}
		    }
		}catch(Exception e){
			MyLog.e(MainActivity.PROCESS_TAG, TAG+"queryAppId - query exception: " + e.getMessage() );
			throw new Exception("queryAppIdException - " + e.getMessage());
		}
	}
	
	private void queryDeviceId()throws Exception{
		try{
			ParseQuery query = new ParseQuery(MyConstants.TN_DEVICES);
			query.whereEqualTo(MyConstants.TF_DEVICES_IMEI, MyUtils.getImei(_context));
			List<ParseObject> list = query.find();
			if( list == null ){
		        MyLog.d(MainActivity.PROCESS_TAG, TAG+"queryDeviceId - device id not found" );
			}
			else{		
	        	if( list.size() == 0 ){
	      		  	MyLog.d(MainActivity.PROCESS_TAG, TAG+"queryDeviceId.size == 0");
		        	//insert device id
		        	ParseObject object = new ParseObject(MyConstants.TN_DEVICES);		    	    
		        	object.put(MyConstants.TF_DEVICES_IMEI, MyUtils.getImei(_context));
		        	try{
		        		object.save();
		        	}catch(Exception e){
		        		MyLog.e(MainActivity.PROCESS_TAG, TAG+"queryDeviceId - save exception: " + e.getMessage() );
		        	}
		        	queryDeviceId();		        			  
		        }
		        else{
			        ParseObject object = list.get(0);		     
		  			MySharedPreferences.setStringProperty(_context, object.getObjectId(), MySharedPreferences.KEY_DEVICES_OBJECT_ID);
			        MyLog.d(MainActivity.PROCESS_TAG, TAG+"queryDeviceId.objectId = " + object.getObjectId());
		        }
			}
		}
		catch(Exception e){
			MyLog.e(MainActivity.PROCESS_TAG, TAG+"queryDeviceId - query exception: " + e.getMessage() );
			throw new Exception("queryDeviceIdException - " + e.getMessage());
		}
	}	
}
